package com.example.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.admin.common.exception.BusinessException;
import com.example.admin.common.util.UserContext;
import com.example.admin.entity.NavGroup;
import com.example.admin.entity.NavLink;
import com.example.admin.mapper.NavGroupMapper;
import com.example.admin.mapper.NavLinkMapper;
import com.example.admin.model.dto.NavGroupDTO;
import com.example.admin.model.dto.NavLinkRequest;
import com.example.admin.service.NavService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class NavServiceImpl implements NavService {

    @Autowired
    private NavGroupMapper navGroupMapper;
    
    @Autowired
    private NavLinkMapper navLinkMapper;

    @Override
    public List<NavGroup> getNavGroups(Long userId) {
        LambdaQueryWrapper<NavGroup> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NavGroup::getGroupStatus, 1) // 只查询启用的分组
                .and(w -> w.isNull(NavGroup::getUserId) // 查询默认分组
                        .or(userId != null, u -> u.eq(NavGroup::getUserId, userId)) // 如果用户已登录,还查询用户的分组
                )
                .orderByAsc(NavGroup::getGroupOrder); // 按排序升序
        return navGroupMapper.selectList(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addNavGroup(NavGroup navGroup) {
        // 检查分组名是否重复
        checkGroupNameDuplicate(navGroup);
        navGroupMapper.insert(navGroup);
        log.info("新增导航分组成功, groupName: {}", navGroup.getGroupName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNavGroup(NavGroup navGroup) {
        // 检查分组名是否重复
        checkGroupNameDuplicate(navGroup);
        navGroupMapper.updateById(navGroup);
        log.info("更新导航分组成功, id: {}, groupName: {}", navGroup.getId(), navGroup.getGroupName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNavGroup(Integer id) {
        // 检查分组下是否有链接
        checkGroupHasLinks(id);
        navGroupMapper.deleteById(id);
        log.info("删除导航分组成功, id: {}", id);
    }

    @Override
    public IPage<NavLink> getNavLinks(NavLinkRequest params) {
        Page<NavLink> page = new Page<>(params.getCurrent(), params.getSize());
        // 构建查询条件
        LambdaQueryWrapper<NavLink> wrapper = new LambdaQueryWrapper<>();
        // 关联分组查询，只查询当前用户的分组下的链接
        wrapper.exists(
            String.format(
                "SELECT 1 FROM nav_groups g WHERE g.id = nav_link.group_id AND (g.user_id = %d OR g.user_id IS NULL)",
                UserContext.getUser().getId()
            )
        );
        // 如果指定了分组，则只查询该分组下的链接
        if (params.getGroupId() != null) {
            wrapper.eq(NavLink::getGroupId, params.getGroupId());
        }
        wrapper.orderByAsc(NavLink::getSortNo);
        
        return navLinkMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addNavLink(NavLink navLink) {
        navLinkMapper.insert(navLink);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNavLink(NavLink navLink) {
        navLinkMapper.updateById(navLink);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNavLink(Integer id) {
        navLinkMapper.deleteById(id);
    }

    @Override
    public void validateGroupOwnership(Integer groupId, Long userId) {
        NavGroup group = navGroupMapper.selectById(groupId);
        if (group == null) {
            throw new BusinessException("分组不存在");
        }
        // 如果不是公共分组，且不属于当前用户
        if (group.getUserId() != null && !group.getUserId().equals(userId)) {
            throw new BusinessException("无权操作此分组");
        }
    }

    /**
     * 检查分组名是否重复
     */
    private void checkGroupNameDuplicate(NavGroup navGroup) {
        LambdaQueryWrapper<NavGroup> wrapper = new LambdaQueryWrapper<NavGroup>()
            .eq(NavGroup::getGroupName, navGroup.getGroupName())
            .eq(NavGroup::getUserId, navGroup.getUserId());
        
        if (navGroup.getId() != null) {
            wrapper.ne(NavGroup::getId, navGroup.getId());
        }
        
        Integer count = navGroupMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BusinessException("分组名称已存在");
        }
    }

    /**
     * 检查分组下是否有链接
     */
    private void checkGroupHasLinks(Integer groupId) {
        Integer count = navLinkMapper.selectCount(
            new LambdaQueryWrapper<NavLink>()
                .eq(NavLink::getGroupId, groupId)
        );
        if (count > 0) {
            throw new BusinessException("该分组下存在链接，无法删除");
        }
    }

    @Override
    public List<NavGroupDTO> getNavData(Long userId) {
        // 1. 获取导航分组
        List<NavGroup> groups = getNavGroups(userId);
        
        // 2. 构建返回数据
        List<NavGroupDTO> result = new ArrayList<>();
        for (NavGroup group : groups) {
            NavGroupDTO dto = BeanUtil.copyProperties(group, NavGroupDTO.class);
            // 3. 获取分组下的链接
            List<NavLink> links = getGroupLinks(group.getId());
            dto.setLinks(links);
            result.add(dto);
        }
        return result;
    }
    
    /**
     * 获取分组下的链接
     */
    private List<NavLink> getGroupLinks(Integer groupId) {
        LambdaQueryWrapper<NavLink> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NavLink::getGroupId, groupId)
            .eq(NavLink::getStatus, 1) // 只查询启用的链接
            .orderByAsc(NavLink::getSortNo); // 按排序升序
            
        return navLinkMapper.selectList(wrapper);
    }
} 